import data_rdb from '@ohos.data.rdb';
import ability_featureAbility from '@ohos.ability.featureAbility';

const TAG = 'rdbStore';
/**
 * 关系型数据库
 */
const DB_NAME = "FocusGameTest7.db";
const STORE_CONFIG = {
    name: DB_NAME
};
const STORE_VERSION = 1;
const TABLE_NAME = "game_info";
const FIGHT_TABLE_NAME = "fight_game_info";
// id-自增长 主键
// NICK_NAME-昵称
// MODEL-游戏模式：对战、简单、中等、困难
// TIME-游戏耗时
// TIME_VAL-游戏耗时值
// GAME_DATE 游戏时间
const SQL_CREATE_TABLE = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (ID INTEGER PRIMARY KEY AUTOINCREMENT, NICK_NAME TEXT NOT NULL, MODEL INTEGER, TIME INTEGER, TIME_VAL TEXT)";
// id-自增长 主键
// NICK_NAME-昵称
// TIME-游戏耗时
// TIME_VAL-游戏耗时值
// GAME_DATE 游戏时间
// FIGHT_ID 对战ID
const SQL_CREATE_FIGHT_TABLE = "CREATE TABLE IF NOT EXISTS " + FIGHT_TABLE_NAME + " (ID INTEGER PRIMARY KEY AUTOINCREMENT, NICK_NAME TEXT NOT NULL, TIME INTEGER, TIME_VAL TEXT, FIGHT_ID TEXT)";

export default class RdbStoreModel {
    rdbStore;
    context = ability_featureAbility.getContext();

    createRdbStore(callback) {
        if (typeof (this.rdbStore) === 'undefined') {
            let self = this;
            let promise = data_rdb.getRdbStore(this.context, STORE_CONFIG, STORE_VERSION)
            promise.then(async (rdbStore) => {
                self.rdbStore = rdbStore;
                await rdbStore.executeSql(SQL_CREATE_TABLE, null);
                console.info(`${TAG} create table done.`);
                await rdbStore.executeSql(SQL_CREATE_FIGHT_TABLE, null);
                console.info(`${TAG} create fight table done.`);
                // 设置分布式同步表
                await rdbStore.setDistributedTables([FIGHT_TABLE_NAME]).then(() => {
                    console.info(`${TAG} setDistributedTables success`);
                }).catch((err) => {
                    console.info(`${TAG} setDistributedTables fail: ${err}`);
                });
                callback();
            }).catch((err) => {
                console.info(`${TAG} kvStore ${err}`)
                callback();
            })
        } else {
            callback();
        }
    }


    /**
     * 删除数据库
     */
    deleteRdbStore() {
        let promise = data_rdb.deleteRdbStore(this.context, DB_NAME);
        promise.then(() => {
            console.info(`${TAG} rdbStore delete Rdb Store done.`)
        })
    }

    /**
     * 插入数据
     */
    insertValue(valueBucket, callback) {
        this.createRdbStore(() => {
            this.insert(TABLE_NAME, valueBucket, callback);
        })
    }

    /**
     * 插入对战数据
     */
    insertFightValue(valueBucket, callback) {
        this.createRdbStore(() => {
            this.insert(FIGHT_TABLE_NAME, valueBucket, callback);
        })
    }

    /**
     * 同步对战数据
     */
    syncFightValue(callback) {
        let self = this;
        this.createRdbStore(() => {
            let predicates = new data_rdb.RdbPredicates(FIGHT_TABLE_NAME)
            predicates.inAllDevices();
            let promise = self.rdbStore.sync(data_rdb.SyncMode.SYNC_MODE_PUSH, predicates);
            promise.then((result) => {
                let syncResult = true;
                for (let i = 0; i < result.length; i++) {
                    console.info(`${TAG} device=${result[i][0]}, status = ${result[i][1]}`);
                    if (result[i][1] != 0) {
                        syncResult = false;
                        break;
                    }
                }
                callback(syncResult);
            }).cache((err) => {
                console.info(`${TAG} sync fail: ${err}`);
            })
        })
    }

    /**
     * 注册数据库的观察者
     */
    async registerSyncListener(callback) {
        let self = this;
        this.createRdbStore(() => {
            try {
                self.rdbStore.on('dataChange', data_rdb.SubscribeType.SUBSCRIBE_TYPE_REMOTE, function storeObserver(devices) {
                    for (let i = 0; i < devices.length; i++) {
                        console.info(`${TAG} device ${devices[i]} data changed`);
                        callback(devices[i]);
                    }
                })
            } catch (err) {
                console.info(`${TAG} register observer failed`)
            }
        });
    }

    /**
     * 删除指定类型的指定观察者
     */
    unregisterSyncListener() {
        let self = this;
        this.createRdbStore(() => {
            try {
                self.rdbStore.off('dataChange', data_rdb.SubscribeType.SUBSCRIBE_TYPE_REMOTE, function storeObserver(devices) {
                    console.info(`${TAG} unregisterSyncListener =${JSON.stringify(devices)}`);
                })
            } catch (err) {
                console.info(`${TAG} unregister observer failed`)
            }
        });
    }

    /**
     * 修改数据
     * @param valueBucket
     * @param index
     */
    updateValue(valueBucket, index) {
        this.createRdbStore(() => {
            this.update(valueBucket, index);
        })
    }

    /**
     * 删除数据
     * @param index
     */
    deleteValue(index) {
        this.createRdbStore(() => {
            this.delete(index);
        })
    }

    queryValue(nickName, callback) {
        let self = this;
        this.createRdbStore(() => {
            let predicates = new data_rdb.RdbPredicates(TABLE_NAME)
            predicates.equalTo("nick_name", nickName);
            let promise = this.rdbStore.query(predicates)
            console.info(`${TAG} rdbStore query start`)
            promise.then((resultSet) => {
                self.displayResult(resultSet, callback);
            })
        })
    }

    displayResult(resultSet, callback) {
        var contactList = []
        if (resultSet.rowCount > 0) {
            var ranking = 0; // 排名
            while (resultSet.goToNextRow()) {
                let id = resultSet.getLong(resultSet.getColumnIndex("ID"));
                let model = resultSet.getLong(resultSet.getColumnIndex("MODEL"));
                let time = resultSet.getLong(resultSet.getColumnIndex("TIME"));
                let timeVal = resultSet.getString(resultSet.getColumnIndex("TIME_VAL"));
                console.info(`${TAG} model: ${model}, time: ${time}, timeVal: ${timeVal},`);
                ranking++;
                const obj = {
                    id: id,
                    model: model,
                    time: time,
                    timeVal: timeVal,
                    ranking: ranking
                }
                contactList.push(obj);
            }
        }
        console.info(`${TAG} resultSet column names: ${resultSet.columnNames}`);
        console.info(`${TAG} resultSet column count: ${resultSet.columnCount}`);
        callback(contactList);
        resultSet.close();
        resultSet = null;
    }

    queryValueByModule(nickName, module, callback) {
        let self = this;
        this.createRdbStore(() => {
            let predicates = new data_rdb.RdbPredicates(TABLE_NAME)
            predicates.equalTo("nick_name", nickName).and().equalTo("model", module).orderByAsc("time");
            let promise = this.rdbStore.query(predicates)
            console.info(`${TAG} rdbStore query start`)
            promise.then((resultSet) => {
                self.displayResult(resultSet, callback);
            })
        })
    }

    queryFirstByModule(nickName, module, callback) {
        this.createRdbStore(() => {
            let predicates = new data_rdb.RdbPredicates(TABLE_NAME)
            predicates.equalTo("nick_name", nickName).and().equalTo("model", module).orderByAsc("time");
            let promise = this.rdbStore.query(predicates)
            console.info(`${TAG} rdbStore query start`)
            promise.then((resultSet) => {
                var time = 0;
                var firstTime = '';
                if (resultSet.rowCount > 0) {
                    resultSet.goToFirstRow();
                    time = resultSet.getLong(resultSet.getColumnIndex("TIME"));
                    firstTime = resultSet.getString(resultSet.getColumnIndex("TIME_VAL"));
                }
                console.info(`${TAG} queryFirstByModule firstTime: ${firstTime}`);
                callback(time, firstTime);
                resultSet.close();
                resultSet = null;
            })
        })
    }

    getFightResult(resultSet) {
        var fightList = []
        let count = resultSet.rowCount;
        console.info(`${TAG} Fight data count:${count}`);
        if (count > 0) {
            while (resultSet.goToNextRow()) {
                let id = resultSet.getLong(resultSet.getColumnIndex("ID"));
                let time = resultSet.getLong(resultSet.getColumnIndex("TIME"));
                let nickName = resultSet.getString(resultSet.getColumnIndex("NICK_NAME"));
                let timeVal = resultSet.getString(resultSet.getColumnIndex("TIME_VAL"));
                let fightId = resultSet.getString(resultSet.getColumnIndex("FIGHT_ID"));
                console.info(`${TAG} Fight data id:${id}, ${time}, ${nickName}, ${timeVal}, ${fightId}`);
                const obj = {
                    id: id,
                    nickName: nickName,
                    time: time,
                    timeVal: timeVal,
                    fightId: fightId
                }
                fightList.push(obj);
            }
        }
        resultSet.close();
        resultSet = null;
        return fightList;
    }

    displayFightResult(resultSet, fightResultSet, callback) {
        var contactList = []
        if (resultSet.rowCount > 0) {
            while (resultSet.goToNextRow()) {
                let id = resultSet.getLong(resultSet.getColumnIndex("ID"));
                let time = resultSet.getLong(resultSet.getColumnIndex("TIME"));
                let nickName = resultSet.getString(resultSet.getColumnIndex("NICK_NAME"));
                let timeVal = resultSet.getString(resultSet.getColumnIndex("TIME_VAL"));
                let fightId = resultSet.getString(resultSet.getColumnIndex("FIGHT_ID"));

                let fightTime = fightResultSet.getLong(fightResultSet.getColumnIndex("TIME"));
                let fightNickName = fightResultSet.getString(fightResultSet.getColumnIndex("NICK_NAME"));
                let fightTimeVal = fightResultSet.getString(fightResultSet.getColumnIndex("TIME_VAL"));
                const obj = {
                    id: id,
                    nickName: nickName,
                    time: time,
                    timeVal: timeVal,
                    fightId: fightId,
                    fightTime: fightTime,
                    fightNickName:fightNickName,
                    fightTimeVal:fightTimeVal
                }
                contactList.push(obj);
            }
        }
        console.info(`${TAG} Fight resultSet column names: ${resultSet.columnNames}`);
        console.info(`${TAG} Fight resultSet column count: ${resultSet.columnCount}`);
        callback(contactList);
        resultSet.close();
        resultSet = null;
    }

    queryFightData(deviceId, nickName, fightId, callback) {
        console.info(`${TAG} ${nickName} queryFightData deviceId= ${deviceId} ,nickName= ${nickName}, fightId= ${fightId}`);
        let self = this;
        this.createRdbStore(async() => {
            console.info(`${TAG} queryFightData start`);
            let tableName = await self.rdbStore.obtainDistributedTableName(deviceId, FIGHT_TABLE_NAME);
            console.info(`${TAG} queryFightData tableName:${tableName}`);
            let predicates = new data_rdb.RdbPredicates(tableName)
            predicates.equalTo("fight_id", fightId);//           predicates.notEqualTo("nick_name", nickName).equalTo("fight_id", fightId);
            let fightResult = await self.rdbStore.query(predicates);
            let fightSet = self.getFightResult(fightResult);
            callback(fightSet);
        });
    }

    async queryValueByFightId(nickName, fightId) {
        console.info(`${TAG} ${nickName} queryValueByFightId fightId ${fightId}`);
        let self = this;
        let fightSet = [];
        await this.createRdbStore(async() => {
            console.info(`${TAG} rdbStore query By FightId start`);
            let predicates = new data_rdb.RdbPredicates(FIGHT_TABLE_NAME)
            predicates.equalTo("fight_id", fightId);//           predicates.notEqualTo("nick_name", nickName).equalTo("fight_id", fightId);
            let fightResult = await self.rdbStore.query(predicates);
            fightSet = self.getFightResult(fightResult);
            console.info(`${TAG} rdbStore query By FightId end`);
        });
        return fightSet;
    }

    queryFightValue(nickName, callback) {
        let self = this;
        this.createRdbStore(() => {
            let predicates = new data_rdb.RdbPredicates(FIGHT_TABLE_NAME)
            predicates.equalTo("nick_name", nickName);
            let promise = this.rdbStore.query(predicates)
            console.info(`${TAG} rdbStore query fight data start`)
            promise.then((resultSet) => {
                console.info(`${TAG} query fight data:${JSON.stringify(resultSet)}`);
                // todo 根据对战ID获取对手的成绩
                let fightList = self.getFightResult(resultSet);
                if (fightList.length > 0) {
                    for (var i = 0; i < fightList.length; i++) {
                        let fightId = fightList[i];
                        console.info(`${TAG} ${nickName} fightId: ${fightId}`);
                        let fightSet = self.queryValueByFightId(nickName, fightId);
                        self.displayFightResult(resultSet, fightSet, callback);
                    }
                } else {
                    console.info(`${TAG} rdbStore query fight data null`);
                    self.displayFightResult(resultSet, [], callback);
                }
            })
        })
    }

    insert(table, valueBucket, callback) {
        console.info(`${TAG} rdbStore insert nick_name: ${valueBucket.nick_name}`);
        let promise = this.rdbStore.insert(table, valueBucket)
        promise.then(async (rows) => {
            await console.info(`${TAG} rdbStore.insert rows: ${rows}`);
            callback(true);
        }).catch((err) => {
            callback(false);
        })
    }

    update(valueBucket, index) {
        console.info(`${TAG} rdbStore update ${index} == ${valueBucket}`);
        let predicates = new data_rdb.RdbPredicates(TABLE_NAME);
        predicates.equalTo("ID", index);
        this.rdbStore.update(valueBucket, predicates, function (err, rows) {
            console.info(`${TAG} rdbStore.update row count: ${rows}`)
        })
    }

    delete(index) {
        console.info(`${TAG} rdbStore delete == ${index}`);
        let predicates = new data_rdb.RdbPredicates(TABLE_NAME);
        predicates.equalTo("ID", index);
        this.rdbStore.delete(predicates, function (err, rows) {
            console.info(`${TAG} rdbStore.delete count: ${rows}`)
        })
    }

    constructor() {

    }
}